package de.karlNet.sambamanager.view.beans.forms;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import javax.annotation.PostConstruct;

import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.NodeUnselectEvent;
import org.primefaces.model.TreeNode;

import de.karlNet.sambamanager.ldapModel.ITypeCheckerCallback;
import de.karlNet.sambamanager.ldapModel.LdapObject;
import de.karlNet.sambamanager.view.beans.ManualLeafHandlingTreeNode;
import de.karlNet.sambamanager.view.beans.trees.LdapTreeBean;

public abstract class SelectableTree extends LdapTreeBean {
	private List<LdapObject> preSelectedNodes = new ArrayList<LdapObject>();
	private HashSet<LdapObject> selectedNodes = new HashSet<LdapObject>();

	private List<String> blacklist = new ArrayList<String>();

	protected abstract ITypeCheckerCallback allowedTypes(
			ManualLeafHandlingTreeNode handlingTreeNode);

	public List<LdapObject> getSelectedLdapNestable() {
		List<LdapObject> ret = new ArrayList<LdapObject>();
		for (LdapObject selectedNode : this.selectedNodes) {
			ret.add(selectedNode);
		}
		return ret;
	}

	@PostConstruct
	public void init() {
		this.blacklist.add("Domain Users".toLowerCase());
		this.myRoot.setSelectable(false);
	}

	@Override
	public void onNodeExpand(NodeExpandEvent event) {
		ManualLeafHandlingTreeNode parent = (ManualLeafHandlingTreeNode) event
				.getTreeNode();
		this.removeNodes(parent);
		for (LdapObject ldapObject : this.getLdapTree().getChildrenOfDN(
				parent.getLdapObject().getDn())) {

			ManualLeafHandlingTreeNode child = new ManualLeafHandlingTreeNode(
					ldapObject, parent);

			this.isAllowed(child);
			if (this.preSelectedNodes.contains(ldapObject)) {
				child.setSelected(true);
			}
		}
	}

	public void isAllowed(ManualLeafHandlingTreeNode handlingTreeNode) {
		handlingTreeNode.getLdapObject().isType(
				this.allowedTypes(handlingTreeNode));
	}

	public void onNodeUnselect(NodeUnselectEvent event) {
		ManualLeafHandlingTreeNode handlingTreeNode = (ManualLeafHandlingTreeNode) (event
				.getTreeNode());
		this.selectedNodes.remove(handlingTreeNode.getLdapObject());
	}

	@Override
	public void onNodeSelect(NodeSelectEvent event) {
		ManualLeafHandlingTreeNode handlingTreeNode = (ManualLeafHandlingTreeNode) (event
				.getTreeNode());
		this.selectedNodes.add(handlingTreeNode.getLdapObject());
	}

	public void setPreSelectedNodes(List<LdapObject> preSelectedNodes) {
		this.selectedNodes.addAll(preSelectedNodes);
		this.preSelectedNodes = preSelectedNodes;
	}

	public void reset() {
		this.selectedNodes = new HashSet<LdapObject>();
		Iterator<TreeNode> i = this.myRoot.getChildren().iterator();
		while (i.hasNext()) {
			i.next();
			i.remove();
		}
		this.myRoot.setExpanded(false);
	}

}